﻿using System;
using System.Drawing;
using System.Linq;
using System.Timers;
using System.Windows.Input;
using GalaSoft.MvvmLight.Command;
using Microsoft.Practices.Prism.Regions;
using Microsoft.Practices.Prism.ViewModel;
using Mipic.Infrastructure;
using Mipic.Infrastructure.Services;
using Mipic.Modules.Mood.Views;

namespace Mipic.Modules.Mood.ViewModels
{
    public class ImageViewModel : NotificationObject
    {
        
        #region //--------- Private Fields --------------//

        private readonly IRegionManager _regionManager;
        
        private readonly IEpocService _epocService;
        private readonly IFilterService _filterService;
        private readonly Timer _timer;
        
        private string _selectedImagePath;
        private Bitmap _selectedImage;
        private int _timeRemaining;
        private string _buttonText;

        private double _frustration;
        private double _excitement;
        private double _engagement;

        private ColorEffectViewModel _colorEffectViewModel;
        
        #endregion
        
        #region //--------- Public Constructors ---------//
        
        public ImageViewModel(IEpocService epocService, IFilterService filterService, IRegionManager regionManager)
        {
            _regionManager = regionManager;
            
            _filterService = filterService;
            _epocService = epocService;
            
            _timer = new Timer();
            _timer.Interval = 1000;
            _timer.Elapsed += OnTimerElapsed;
        
            ButtonText = "START";
        }
        
        #endregion
        
        #region //--------- CLR Properties --------------//
        
        /// <summary>
        /// Gets or sets the selected image path.
        /// </summary>
        /// <value>The selected image path.</value>
        public string SelectedImagePath
        {
            get
            {
                return _selectedImagePath;
            }
            set
            {
                if (_selectedImagePath != value)
                {
                    _selectedImagePath = value;
                    RaisePropertyChanged(() => this.SelectedImagePath);
                
                    SelectedImage = Bitmap.FromFile(SelectedImagePath) as Bitmap;
                }
            }
        }
        
        /// <summary>
        /// Gets or sets the selected image.
        /// </summary>
        /// <value>The selected image.</value>
        public Bitmap SelectedImage
        {
            get
            {
                return _selectedImage;
            }
            set
            {
                if (_selectedImage != value)
                {
                    _selectedImage = value;
                    RaisePropertyChanged(() => this.SelectedImage);
                }
            }
        }
        
        /// <summary>
        /// Gets the time remaining.
        /// </summary>
        /// <value>The time remaining.</value>
        public int TimeRemaining
        {
            get
            {
                return _timeRemaining;
            }
            set
            {
                if (_timeRemaining != value)
                {
                    _timeRemaining = value;
                    RaisePropertyChanged(() => this.TimeRemaining);
                }
            }
        }
        
        public string ButtonText
        {
            get
            {
                return _buttonText;
            }
            set
            {
                if (_buttonText != value)
                {
                    _buttonText = value;
                    RaisePropertyChanged(() => this.ButtonText);
                }
            }
        }
        
        #endregion
        
        #region //--------- Public Commands -------------//
        
        public ICommand StartCommand
        {
            get
            {
                return new RelayCommand(StartExecute);
            }
        }
        
        #endregion

        #region //--------- Event Handlers --------------//
        
        /// <summary>
        /// Called when [timer elapsed].
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="args">The <see cref="System.Timers.ElapsedEventArgs" /> instance containing the event data.</param>
        private void OnTimerElapsed(object sender, ElapsedEventArgs args)
        {
            this.TimeRemaining--;
            
            if (this.TimeRemaining == 5)
            {
                _excitement = _epocService.GetExcitement();
                _frustration = _epocService.GetFrustration();

                string filterName = GetFilterName(_excitement, _frustration);
            
                SelectedImage = _filterService.Apply(SelectedImage, filterName);
            }

            if (this.TimeRemaining == 28)
            {
                _colorEffectViewModel.IsShowBorder = true;
                _colorEffectViewModel.BorderRow = GetFilterNumber(_excitement);
                _colorEffectViewModel.BorderColumn = GetFilterNumber(_frustration);

                _timer.Stop();
            }
        }
        
        /// <summary>
        /// Gets the name of the filter.
        /// </summary>
        /// <param name="frustration">The frustration.</param>
        /// <param name="engagement">The engagement.</param>
        /// <returns>The name of the filter corresponding to frustration and engagement.</returns>
        private string GetFilterName(double excitement, double engagement)
        {
            return String.Format("Filter{0}{1}", GetFilterNumber(excitement), GetFilterNumber(engagement));
        }
        
        /// <summary>
        /// Gets the filter number.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns></returns>
        private int GetFilterNumber(double value)
        {
            if (0 <= value && value <= 0.2)
            {
                return 5;
            }
            else if (0.2 < value && value <= 0.4)
            {
                return 4;
            }
            else if (0.4 < value && value <= 0.6)
            {
                return 3;
            }
            else if (0.6 < value && value <= 0.8)
            {
                return 2;
            }
            else if (0.8 < value && value <= 1)
            {
                return 1;
            }
            else
            {
                return 0;
            }
        }

        #endregion
        
        #region //--------- Private Fields --------------//
        
        /// <summary>
        /// Starts the execute.
        /// </summary>
        private void StartExecute()
        {
            _colorEffectViewModel = (_regionManager.Regions[RegionNames.MoodViewSideBarInfoRegionName].GetView("ColorEffectView") as ColorEffectView).ViewModel;

            if (ButtonText.Equals("START"))
            {
                _epocService.Start();
                _timer.Start();
                this.TimeRemaining = 30;
            
                ButtonText = "DISCARD";
            }
            else if (ButtonText.Equals("DISCARD"))
            {
                _epocService.Stop();
                _timer.Stop();
                this.TimeRemaining = 30;
            
                ButtonText = "START";
            }
        }

        #endregion

    }
}